﻿using System;

namespace Faml.Frontend
{
    public class FamlLambdaParameterExpression : FamlParameterExpression<FamlLambdaParameter>
    {
        public FamlLambdaParameterExpression(FamlLambdaParameter p)
            : base(p)
        {
            MakeMetadata();
        }

        public override FamlExpression Expand()
        {
            return new FamlLambdaParameterExpression(parameter);
        }

        protected override Type ComputeType()
        {
            return parameter.Type;
        }

        protected override void MakeMetadata()
        {
            this.metadata.Height = 1;
            this.metadata.Hash = NodeType.GetHashCode() ^ parameter.Hash;
            this.metadata.AddIfNotExist(parameter);
        }

        public override FamlExpressionType NodeType
        {
            get { return FamlExpressionType.LambdaParameter; }
        }
    }

    public abstract class FamlLambdaParameterDescription
    {
    }

    public class FamlLambdaParameterRange<T> : FamlLambdaParameterDescription
    {
        private T min;
        private T max;

        public T Min
        {
            get { return min; }
            set { min = value; }
        }

        public T Max
        {
            get { return max; }
            set { max = value; }
        }

        public override string ToString()
        {
            return String.Format("{0} : {1}", min, max);
        }
    }

    public class FamlLambdaParameter
    {
        /// <summary>Parameter name</summary>
        private string name;
        /// <summary>Parameter type or null if parameter type is not specified</summary>
        private Type type;

        private FamlLambdaParameterDescription desc = null;


        public FamlLambdaParameter(string name, Type type)
        {
            this.name = name;
            this.type = type;
        }

        public FamlLambdaParameter(string name)
        {
            this.name = name;
            this.type = null;
        }

        public FamlLambdaParameterDescription Description
        {
            get { return desc; }
            set { desc = value; }
        }

        public override string ToString()
        {
            if (type != null)
            {
                if(desc != null)
                    return String.Format("{0}[{2}] {1}", type.Name, name, desc);
                return String.Format("{0} {1}", type.Name, name);
            }
            else
                return name;
        }

        public string Name
        {
            get
            {
                return name;
            }
        }

        public Type Type
        {
            get
            {
                return type;
            }
        }

        public int Hash
        {
            get
            {
                return type.GetHashCode();// ^ name.GetHashCode();
            }
        }
    }
}